//
//  Texture.hpp
//  RayTracer
//
//  Created by 俞云康 on 2/15/16.
//  Copyright © 2016 yushroom. All rights reserved.
//

#ifndef Texture_hpp
#define Texture_hpp

#include "Math.hpp"
#include "Color.hpp"
#include <vector>

class Params;

class Texture {
public:
    string name;
    virtual ~Texture() {};
    virtual Color sample(float u, float v) = 0;
    Color sample(const float2& uv) {
        return sample(uv.x, uv.y);
    }
    
    static std::vector<shared_ptr<Texture>> textures;
    static shared_ptr<Texture> create(const Params& params);
};

class ConstantTexture : public Texture {
private:
    Color color;

public:
    ConstantTexture(const Color& color);
    
    static shared_ptr<Texture> create(const Params& params);
    
    inline virtual Color sample(float u, float v) override {
        return color;
    }
};

class CheckBoard : public Texture {
private:
    Color color1;
    Color color2;
    int x_count;
    int y_count;
    float inv_x_count;
    float inv_y_count;
    
public:
    CheckBoard(const Color& color1,
               const Color& color2,
               const int  x_count,
               const int  y_count);
    
    static shared_ptr<Texture> create(const Params& params);
    
    inline virtual Color sample(float u, float v) override {
        if (u < 0) u -= inv_x_count;
        if (v < 0) v -= inv_y_count;
        return ((int(u*x_count) + int(v*y_count)) & 1) ? color1 : color2;
    }
    
//    static CheckBoard& default_texture() {
//        static CheckBoard cbd({0, 0, 0}, {1, 1, 1}, 8, 8);
//        return cbd;
//    }
};

class Bitmap : public Texture {
private:
    //string path;
    const int mWidth;
    const int mHeight;
    vector<Color> mPixels;
    
public:
    Bitmap(const int width,
           const int height,
           const vector<unsigned char>& pixels,
           const int bitsPerPixel = 24,
           const bool verticalFlip = false);
    
    static shared_ptr<Texture> create(const Params& params);
    
    virtual Color sample(float u, float v) override;
    
    const vector<Color>& getPixels() const {
        return mPixels;
    }
};

#endif /* Texture_hpp */
